

#include "connection.hpp"
#include "InetAddr.hpp"

#define SIZE 1024
// 普通的fd
class Channel : public Connection
{
public:
    Channel(int sockfd,const InetAddr& client)
    :_sockfd(sockfd),_client_addr(client)
    {
        SetNonBlock(_sockfd);
    }
    void Recv() override
    {
        char buff[1024];
        //ET 非阻塞轮询读取
        while(true)
        {
            buff[0]=0;
            ssize_t n=recv(_sockfd,buff,sizeof(buff)-1,0);//非阻塞读取
            if(n>0)
            {
                buff[n]=0;
                _inbuffer+=buff;
            }
            else if(n==0)
            {
                Excpeter();
                return;
            }
            else
            {
                if(errno==EAGAIN||errno==EWOULDBLOCK)
                {
                    break;
                }
                else if(errno==EINTR)
                {
                    continue;
                }
                else
                {
                    Excpeter();
                    return;
                }
            }
        }
        if(!_inbuffer.empty())
            _outbuffer+=_handler(_inbuffer);

        if(!_outbuffer.empty())
            Send();//直接发送
    }
    void Send() override
    {
        //对于写事件，默认是就绪的，最佳实践是直接发
        //如果缓冲区满了，将对应文件描述符的写事件添加epoll管理
        //当添加写事件时 ，默认就会触发一次写事件就绪，然后将(剩余)数据发送
        while(true)
        {
            ssize_t n=send(_sockfd,_outbuffer.c_str(),_outbuffer.size(),0);
            if(n>0)
            {
                _outbuffer.erase(0,n);
                if(_outbuffer.empty())
                    break;//数据发送完了
            }
            else if(n==0)
            {
                break;
            }
            else
            {
                if(errno==EAGAIN||errno==EWOULDBLOCK)
                {
                    //缓冲区满了
                    break;
                }
                else if(errno==EINTR)
                {
                    continue;
                }
                else
                {
                    Excpeter();
                    return;
                }
            }
        }

        //走到这，有两种情况，缓冲区满了和数据发送完毕了
        //1.缓冲区满了
        if(!_outbuffer.empty())
        {
            //开启对写事件的关心
            //读事件常设
            GetOwner()->EnableReadWrite(_sockfd,true,true);
        }
        else
        {
            //数据发送完毕了
            GetOwner()->EnableReadWrite(_sockfd,true,false);
        }
    }
    void Excpeter() override
    {
        GetOwner()->DelConnection(_sockfd);
    }
    int getFd()override
    {
        return _sockfd;
    }
private:
    int _sockfd;
    std::string _inbuffer;  // 接受缓冲区
    std::string _outbuffer; // 发送缓冲区
    InetAddr _client_addr;
};